﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Xml;
using Sripirom.ATS.Core.Helpers;
using Sripirom.ATS.Core.Logging;
using Sripirom.ATS.Core.Messaging;
using Sripirom.ATS.Core.UnitOfWork;
using Sripirom.ATS.Model.ServiceLog;

namespace Sripirom.ATS.Services.MessageInspectors
{
    public class ServiceTransactionLogInspector : IDispatchMessageInspector
    {
        private readonly IUnitOfWork _uow;
        private readonly IServiceTransactionLogRepository _serviceTransactionLogRepository;
        public ServiceTransactionLogInspector(IUnitOfWork uow,
            IServiceTransactionLogRepository serviceTransactionLogRepository)
        {
            _uow = uow;
            _serviceTransactionLogRepository = serviceTransactionLogRepository;
        }

        public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
        {
            LoggerFactory.CreateLog().Debug("I:AfterReceiveRequest");
            ServiceTransactionLog serviceLog = new ServiceTransactionLog();
            ServiceMessageHeader header = ServiceHeader.ReadHeader(request);

            String soapRequest =  request.ToString();
            serviceLog.ChanelRequest = StringCompressor.CompressString(soapRequest);
            serviceLog.TransactionId = header.TransactionId;
            serviceLog.ChannelCode = header.ChannelId;
            serviceLog.Status = ServiceStatus.EX;

            
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.LoadXml(soapRequest);
            XmlNamespaceManager ns = new XmlNamespaceManager(xmldoc.NameTable);
            ns.AddNamespace("body", request.Headers.Action + "/RequestMessage/Body");

            serviceLog.CompanyCode = xmldoc.SelectSingleNode("//body:CompanyCode", ns).InnerText;
            serviceLog.ServiceCode = xmldoc.SelectSingleNode("//body:ServiceCode", ns).InnerText;
            serviceLog.SubServiceCode = xmldoc.SelectSingleNode("//body:SubServiceCode", ns).InnerText;
            serviceLog.TranferType = xmldoc.SelectSingleNode("//body:TransferType", ns).InnerText;
            serviceLog.CreatedBy = header.Username;
            serviceLog.CreatedDate = DateTime.Now;
         

            object correlationState = _serviceTransactionLogRepository.Add(serviceLog);

            LoggerFactory.CreateLog().Debug("O:AfterReceiveRequest");


            string sysServiceTransactionId = "SysServiceTransactionId";
            if (OperationContext.Current.IncomingMessageProperties.ContainsKey(sysServiceTransactionId))
                OperationContext.Current.IncomingMessageProperties[sysServiceTransactionId] = correlationState;
            else
                OperationContext.Current.IncomingMessageProperties.Add(sysServiceTransactionId, correlationState);

            return correlationState;
        }

        public void BeforeSendReply(ref Message reply, object correlationState)
        {
            LoggerFactory.CreateLog().Debug("I:BeforeSendReply");
            ServiceMessageHeader header = ServiceHeader.ReadHeader(reply);
            ServiceTransactionLog serviceLog = _serviceTransactionLogRepository.FindBy((Decimal)correlationState);
           
            String soapReply  = reply.ToString();
            serviceLog.ChannelReply = StringCompressor.CompressString(soapReply) ;

            XmlDocument xmldoc = new XmlDocument();
            xmldoc.LoadXml(soapReply);
            XmlNamespaceManager ns = new XmlNamespaceManager(xmldoc.NameTable);

            ns.AddNamespace("out", "http://www.kiatnakinbank.com/services/ATS/MessageOutput");

            var Output = new MessageOutput()
            {
                Result = xmldoc.SelectSingleNode("//out:Result", ns).InnerText,
                ErrorReason = xmldoc.SelectSingleNode("//out:ErrorReason", ns).InnerText,
            };



            serviceLog.Output = Output;
            serviceLog.UpdatedBy = header.Username;
            serviceLog.UpdatedDate = DateTime.Now;

            _serviceTransactionLogRepository.Save(serviceLog);
            _uow.Commit();

            LoggerFactory.CreateLog().Debug("O:BeforeSendReply");
        }

 
    }
}
